using System.Linq;
using System.Threading.Tasks;
using Furion.FriendlyException;
using PMP.Core.Entities;
using PMP.Core.Enums;
using PMP.Core.SqlSugar;
using SqlSugar;

namespace PMP.Core.Extensions;

public class ScoreHelper
{
    public static async Task<TbAccountScore> GetAndUpdateScore(int accountId,int year)
    {
        var account = await DbContext.Instance.Queryable<TbAccount>()
            .Where(a => a.Id == accountId )
            .FirstAsync();

        if (account == null)
            throw Oops.Bah("当前用户不存在。");
        
        var scoreModel = await DbContext.Instance.Queryable<TbAccountScore>()
            .Where(a => a.AccountId == accountId && a.Year == year)
            .SingleAsync();
        scoreModel ??= new TbAccountScore
        {
            AccountId = accountId,
            Year = year
        };
        (scoreModel.ProjectRecommendationScore,_) = await ProjectRecommendationScore(account,year);
        (scoreModel.TeamDevelopmentScore,_) = await TeamDevelopmentScore(account,year);
        (scoreModel.BusinessAchievementScore,_) = await BusinessAchievementScore(account,year);
        (scoreModel.ResponseTimeScore,scoreModel.ResponseTime) = await ResponseTimeScore(account,year);

        await DbContext.Instance.Storageable(scoreModel).ExecuteCommandAsync();

        var avg = await DbContext.Instance.Queryable<TbAccountScore>()
            .Where(a => a.Year == year)
            .AvgAsync(a => a.ProjectRecommendationScore + a.TeamDevelopmentScore +
                                                a.BusinessAchievementScore + a.ResponseTimeScore);
        scoreModel.AvgTotalScore = avg;
        return scoreModel;
    }

    /// <summary>
    /// 项目推荐
    /// </summary>
    /// <param name="account"></param>
    /// <returns>1.评分；2.推荐相关等级的项目数</returns>
    private static async Task<(int,int)> ProjectRecommendationScore(TbAccount account,int year)
    {
        var projects = await DbContext.Instance.Queryable<TbProject>()
            .Where(a => a.CreateUserId == account.Id)
            .WhereIF(year!=0,a=>a.CreateTime.Year == year)
            .ToListAsync();

        var pCount = 0;
        var isPass = false;
        if (account.UserLevel == EnumUserLevel.Level0)
        {
            pCount = projects.Count();
            isPass = pCount > 5;
            isPass = isPass && (projects.Count(p => p.ProjectLevel >= EnumProjectLevel.Level1) >= pCount * 0.4
                                || projects.Count(p => p.ProjectLevel >= EnumProjectLevel.Level2) >= pCount * 0.2);
        }
        else if (account.UserLevel == EnumUserLevel.Level1)
        {
            pCount = projects.Count(p => p.ProjectLevel == EnumProjectLevel.Level1);
            isPass = pCount > 5;
            isPass = isPass && (projects.Count(p => p.ProjectLevel >= EnumProjectLevel.Level2) >= pCount * 0.4
                                || projects.Count(p => p.IsFinished) >= pCount * 0.2);
        }
        else
        {
            pCount  =projects.Count(p => p.ProjectLevel == EnumProjectLevel.Level2);
            isPass = pCount > 5;
            isPass = isPass && (projects.Count(p => p.IsFinished) >= pCount * 0.4);
        }
        var score = isPass ? 30 : 0;
        return (score,pCount);
    }
    
    /// <summary>
    /// 团队发展
    /// </summary>
    /// <param name="account"></param>
    /// <returns>1.评分；2.推荐相关等级的人数</returns>
    private static async Task<(int,int)> TeamDevelopmentScore(TbAccount account,int year)
    {
        var accounts = await DbContext.Instance.Queryable<TbAccount>()
            .Where(a => a.ReferrerUserId == account.Id)
            .WhereIF(year!=0,a=>a.CreateTime.Year == year)
            .ToListAsync();
        var count = 0;
        var isPass = false;
        if (account.UserLevel == EnumUserLevel.Level0)
        {
            count = accounts.Count();
            isPass = count > 2;
        }
        else if (account.UserLevel == EnumUserLevel.Level1)
        {
            count = accounts.Count(a=>a.UserLevel >= EnumUserLevel.Level1);
            isPass = count > 2;
        }
        else
        {
            count = accounts.Count(a=>a.UserLevel >= EnumUserLevel.Level1);
            isPass = count > 2;
        }
        var score = isPass ? 10 : 0;
        return (score,count);
    }
    
    /// <summary>
    /// 业务达成
    /// </summary>
    /// <param name="account"></param>
    /// <returns>1.评分；2.业务达成数</returns>
    private static async Task<(int,int)> BusinessAchievementScore(TbAccount account,int year)
    {
        var projects = await DbContext.Instance.Queryable<TbProject>()
            .Where(a => a.CreateUserId == account.Id)
            .WhereIF(year!=0,a=>a.CreateTime.Year == year)
            .ToListAsync();
        var count = 0;
        if (account.UserLevel == EnumUserLevel.Level0)
        {
            count = projects.Count(p => p.IsFinished);
        }
        else if (account.UserLevel == EnumUserLevel.Level1)
        {
            count = projects.Count(p => p.IsFinished);
        }
        else
        {
            count = projects.Count(p => p.IsFinished && p.Income>100);
        }
        var score = count > 0 ? 40 : 0;
        return (score,count);
    }
    
    
    /// <summary>
    /// 响应时间
    /// </summary>
    /// <param name="account"></param>
    /// <returns>1.评分；2.平均响应时间</returns>
    private static async Task<(int,double)> ResponseTimeScore(TbAccount account,int year)
    {
        var tasks = await DbContext.Instance.Queryable<TbNotification>()
            .Where(a => a.TargetUserId == account.Id && a.IsDeal == true)
            .WhereIF(year!=0,a=>a.CreateTime.Year == year)
            .ToListAsync();
        var avg = tasks.Count > 0 ? tasks.Average(a => a.DealTime!.Value.Subtract(a.CreateTime).TotalHours) : 0;
        var isPass = false;
        if (account.UserLevel == EnumUserLevel.Level0)
        {
            isPass = avg > 0 && avg<=5;
        }
        else if (account.UserLevel == EnumUserLevel.Level1)
        {
            isPass =avg > 0 && avg<=4;
        }
        else
        {
            isPass =avg > 0 && avg<=3;
        }
        var score = isPass ? 40 : 0;
        return (score,avg);
    }
}